﻿using BCCommon;
using BCCommon.Enums;
using BCData.Common.WebsiteConfiguration;
using BCData.WeChatComponent.WeChatMediaRecord;
using BCData.WeChatComponent.WeChatNewsMaterialArticleRecord;
using BCDto.WeChatComponent.WeChatMediaRecord;
using BCEntity.WeChatComponent.WeChatMediaRecord;
using BCEntity.WeChatComponent.WeChatNewsMaterialArticleRecord;
using BCService.Utils;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using WeChatSDK.Common.Enums.Material;
using WeChatSDK.WeChatDto.Request.Http;
using WeChatSDK.WeChatServiceComponent.Material;

namespace BCService.WeChatComponent.WeChatMediaRecordService
{
    /// <summary>
    /// 微信素材记录服务
    /// </summary>
    public class WeChatMediaRecordService : IWeChatMediaRecordService
    {
        private readonly IConfiguration configuration;
        private readonly IWeChatMediaRecordData weChatMediaRecordData;
        private readonly IWebsiteConfigurationData websiteConfigurationData;
        private readonly IWeChatNewsMaterialArticleRecordData weChatNewsMaterialArticleRecordData;
        private readonly MaterialService materialService;
        public WeChatMediaRecordService(IConfiguration configuration,
            IWeChatMediaRecordData weChatMediaRecordData,
            IWebsiteConfigurationData websiteConfigurationData,
            IWeChatNewsMaterialArticleRecordData weChatNewsMaterialArticleRecordData)
        {
            this.configuration = configuration;
            this.weChatMediaRecordData = weChatMediaRecordData;
            this.websiteConfigurationData = websiteConfigurationData;
            this.weChatNewsMaterialArticleRecordData = weChatNewsMaterialArticleRecordData;
            this.materialService = new MaterialService();
        }

        public bool Add(WeChatMediaRecordDto weChatMediaRecordDto)
        {
            if (string.IsNullOrWhiteSpace(weChatMediaRecordDto.MediaId))
            {
                throw new ArgumentException("微信素材Id不能为空。");
            }
            if (this.weChatMediaRecordData.CheckMediaExists(weChatMediaRecordDto.MediaId))
            {
                throw new ArgumentException("微信素材记录已经存在，不能重复添加。");
            }
            if (string.IsNullOrWhiteSpace(weChatMediaRecordDto.FileName))
            {
                throw new ArgumentException("文件名称不能为空。");
            }
            if (string.IsNullOrWhiteSpace(weChatMediaRecordDto.Title))
            {
                throw new ArgumentException("素材的标题不能为空。");
            }
            if (string.IsNullOrWhiteSpace(weChatMediaRecordDto.Description))
            {
                throw new ArgumentException("素材的描述不能为空。");
            }
            if (!weChatMediaRecordDto.IsTemporary)
            {
                if (weChatMediaRecordDto.Type == WeChatMediaType.Image)
                {
                    if (string.IsNullOrWhiteSpace(weChatMediaRecordDto.Url))
                    {
                        throw new ArgumentException("图片素材的图片Url不能为空。");
                    }
                }
            }
            return this.weChatMediaRecordData.Add(weChatMediaRecordDto.As<WeChatMediaRecordEntity>());
        }

        public WeChatMediaRecordCountDto Count()
        {
            MaterialService materialService = new MaterialService();
            dynamic result = null;
            try
            {
                string response = WeChatHttpResponseHandle.ProcessMessage(materialService.GetPermanentMaterialCount());
                result = JsonConvert.DeserializeObject<dynamic>(response);
                WeChatMediaRecordCountDto weChatMediaRecordCountDto = this.weChatMediaRecordData.Count().As<WeChatMediaRecordCountDto>();
                weChatMediaRecordCountDto.WeChatServerImageCount = result.image_count;
                weChatMediaRecordCountDto.WeChatServerLocalVoiceCount = result.voice_count;
                weChatMediaRecordCountDto.WeChatServerLocalVideoCount = result.video_count;
                weChatMediaRecordCountDto.WeChatServerLocalNewsCount = result.news_count;
                return weChatMediaRecordCountDto;
            }
            catch
            {
                if (result == null)
                {
                    result = new
                    {
                        image_count = 0,
                        voice_count = 0,
                        video_count = 0,
                        news_count = 0
                    };
                }
                WeChatMediaRecordCountDto weChatMediaRecordCountDto = this.weChatMediaRecordData.Count().As<WeChatMediaRecordCountDto>();
                weChatMediaRecordCountDto.WeChatServerImageCount = result.image_count;
                weChatMediaRecordCountDto.WeChatServerLocalVoiceCount = result.voice_count;
                weChatMediaRecordCountDto.WeChatServerLocalVideoCount = result.video_count;
                weChatMediaRecordCountDto.WeChatServerLocalNewsCount = result.news_count;
                return weChatMediaRecordCountDto;
            }
        }

        public void Delete(string mediaId)
        {
            WeChatMediaRecordEntity weChatMediaRecordEntity = this.weChatMediaRecordData.GetEntity(mediaId);
            if (weChatMediaRecordEntity == null)
            {
                throw new ArgumentException("此素材并不存在。");
            }
            if (!weChatMediaRecordEntity.IsTemporary)
            {
                MaterialService materialService = new MaterialService();
                if (materialService.DeletePermanentMaterial(mediaId).IsError)
                {
                    throw new ArgumentException("删除微信素材失败。");
                }
            }
            if (weChatMediaRecordEntity.Type == WeChatMediaType.News)
            {
                this.weChatNewsMaterialArticleRecordData.Delete(mediaId);
            }
            this.weChatMediaRecordData.Delete(mediaId);
        }

        public void Delete(string[] mediaIds)
        {
            foreach (string id in mediaIds)
            {
                this.Delete(id);
            }
        }

        public WeChatMediaRecordDto GetEntity(string mediaId)
        {
            var entity = this.weChatMediaRecordData.GetEntity(mediaId);
            //string websiteHost = configuration["CurrentlyImageHost"];
            //if (!string.IsNullOrWhiteSpace(entity.LocalUrl))
            //{
            //    entity.LocalUrl = string.Concat(websiteHost, entity.LocalUrl);
            //}
            return entity.As<WeChatMediaRecordDto>();
        }

        public PageableList<WeChatMediaRecordDto> GetRecords(string mediaId, string fileName, DateTime? start, DateTime? end, string fileType, bool? isTemporary, bool? ascending, int pageIndex = 1, int pageSize = 10)
        {
            var list = this.weChatMediaRecordData.GetRecords(mediaId, fileName, start, end, fileType, isTemporary, ascending, out int dataCount, pageIndex, pageSize);
            //string websiteHost = configuration["CurrentlyImageHost"];
            //foreach (var item in list)
            //{
            //    item.LocalUrl = string.Concat(websiteHost, item.LocalUrl);
            //}
            return new PageableList<WeChatMediaRecordDto>
            {
                Count = dataCount,
                Items = list.Select(p => p.As<WeChatMediaRecordDto>())
            };
        }

        public void SynchronizeWeChatPermanentMaterial()
        {
            MaterialType[] materialTypes = new MaterialType[] { MaterialType.Image, MaterialType.News, MaterialType.Video, MaterialType.Voice };
            MaterialService materialService = new MaterialService();
            WeChatMediaRecordCountDto weChatMediaRecordCountDto = this.Count();
            foreach (MaterialType type in materialTypes)
            {
                int count = 0;
                switch (type)
                {
                    case MaterialType.Image:
                        count = weChatMediaRecordCountDto.WeChatServerImageCount;
                        break;
                    case MaterialType.Video:
                        count = weChatMediaRecordCountDto.WeChatServerLocalVideoCount;
                        break;
                    case MaterialType.Voice:
                        count = weChatMediaRecordCountDto.WeChatServerImageCount;
                        break;
                    case MaterialType.News:
                        count = weChatMediaRecordCountDto.WeChatServerImageCount;
                        break;
                }
                for (int i = 0; i < count; i++)
                {
                    string response = WeChatHttpResponseHandle.ProcessMessage(materialService.GetPermanentMaterialList(type, i, 20));
                    dynamic result = JsonConvert.DeserializeObject<dynamic>(response);
                    WeChatMediaType weChatMediaType = (WeChatMediaType)Enum.Parse(typeof(WeChatMediaType), type.ToString());
                    int itemCount = (int)result.item_count;
                    if (type == MaterialType.News)
                    {
                        for (int j = 0; j < itemCount; j++)
                        {
                            string mediaId = result.item[j].media_id;
                            string path = "";
                            if (this.weChatMediaRecordData.CheckMediaExists(mediaId))
                            {
                                WeChatMediaRecordDto newsContent = new WeChatMediaRecordDto()
                                {
                                    Type = weChatMediaType,
                                    MediaId = mediaId,
                                    CreatedAt = result.item[j].update_time,
                                    IsTemporary = false
                                };
                                weChatNewsMaterialArticleRecordData.Delete(newsContent.MediaId);
                                for (int x = 0; x < (int)result.item[j].content.news_item.Count; x++)
                                {
                                    if (x == 0)
                                    {
                                        newsContent.FileName = result.item[j].content.news_item[x].title;
                                        newsContent.Title = result.item[j].content.news_item[x].title;
                                        newsContent.Description = result.item[j].content.news_item[x].digest;
                                        newsContent.Url = result.item[j].content.news_item[x].content_source_url;
                                    }

                                    long time = (long)result.item[j].update_time;
                                    DateTime start = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
                                    DateTime updateTime = start.AddMilliseconds(time).ToLocalTime();
                                    string thumbMediaId = result.item[j].content.news_item[x].thumb_media_id;
                                    string thumbUrl = result.item[j].content.news_item[x].thumb_url;
                                    if (!string.IsNullOrWhiteSpace(thumbUrl))
                                    {
                                        path = SaveImage(WeChatMediaType.Thumb, time.ToString() + "_" + x + ".jpg", thumbUrl).Replace("\\", "/");
                                        this.weChatMediaRecordData.UpdateMediaTypeForThumb(thumbMediaId, path);
                                    }
                                    weChatNewsMaterialArticleRecordData.Add(new WeChatNewsMaterialArticleRecordEntity()
                                    {
                                        Title = result.item[j].content.news_item[x].title,
                                        ThumbMediaId = thumbMediaId,
                                        ShowCoverPic = result.item[j].content.news_item[x].show_cover_pic,
                                        Author = result.item[j].content.news_item[x].author,
                                        Digest = result.item[j].content.news_item[x].digest,
                                        Content = result.item[j].content.news_item[x].content,
                                        ContentSourceUrl = result.item[j].content.news_item[x].content_source_url,
                                        MediaId = mediaId,
                                        UpdateTime = updateTime,
                                        NeedOpenComment = result.item[j].content.news_item[x].need_open_comment,
                                        OnlyFansCanComment = result.item[j].content.news_item[x].only_fans_can_comment,
                                        Index = x,
                                        ThumbUrl = thumbUrl,
                                        ImageUrl = path
                                    });
                                }
                                this.weChatMediaRecordData.Update(newsContent.As<WeChatMediaRecordEntity>());
                            }
                            else
                            {
                                WeChatMediaRecordDto newsContent = new WeChatMediaRecordDto()
                                {
                                    Type = weChatMediaType,
                                    MediaId = mediaId,
                                    CreatedAt = result.item[j].update_time,
                                    IsTemporary = false
                                };
                                weChatNewsMaterialArticleRecordData.Delete(newsContent.MediaId);
                                for (int x = 0; x < (int)result.item[j].content.news_item.Count; x++)
                                {
                                    if (x == 0)
                                    {
                                        newsContent.FileName = result.item[j].content.news_item[x].title;
                                        newsContent.Title = result.item[j].content.news_item[x].title;
                                        newsContent.Description = result.item[j].content.news_item[x].digest;
                                        newsContent.Url = result.item[j].content.news_item[x].content_source_url;
                                    }

                                    long time = (long)result.item[j].update_time;
                                    DateTime start = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
                                    DateTime updateTime = start.AddMilliseconds(time).ToLocalTime();
                                    string thumbMediaId = result.item[j].content.news_item[x].thumb_media_id;
                                    string thumbUrl = result.item[j].content.news_item[x].thumb_url;
                                    if (!string.IsNullOrWhiteSpace(thumbUrl))
                                    {
                                        path = SaveImage(WeChatMediaType.Thumb, time.ToString() + "_" + x + ".jpg", thumbUrl).Replace("\\", "/");
                                        this.weChatMediaRecordData.UpdateMediaTypeForThumb(thumbMediaId, path);
                                    }
                                    weChatNewsMaterialArticleRecordData.Add(new WeChatNewsMaterialArticleRecordEntity()
                                    {
                                        Title = result.item[j].content.news_item[x].title,
                                        ThumbMediaId = thumbMediaId,
                                        ShowCoverPic = result.item[j].content.news_item[x].show_cover_pic,
                                        Author = result.item[j].content.news_item[x].author,
                                        Digest = result.item[j].content.news_item[x].digest,
                                        Content = result.item[j].content.news_item[x].content,
                                        ContentSourceUrl = result.item[j].content.news_item[x].content_source_url,
                                        MediaId = mediaId,
                                        UpdateTime = updateTime,
                                        NeedOpenComment = result.item[j].content.news_item[x].need_open_comment,
                                        OnlyFansCanComment = result.item[j].content.news_item[x].only_fans_can_comment,
                                        Index = x,
                                        ThumbUrl = thumbUrl,
                                        ImageUrl = path
                                    });
                                }
                                this.Add(newsContent);
                            }
                        }
                    }
                    else
                    {
                        for (int j = 0; j < itemCount; j++)
                        {
                            string mediaId = result.item[j].media_id;
                            if (this.weChatMediaRecordData.CheckMediaExists(mediaId))
                            {
                                WeChatMediaRecordEntity weChatMediaRecordEntity = this.weChatMediaRecordData.GetEntity(mediaId);
                                string localUrl = Regex.Replace(weChatMediaRecordEntity.LocalUrl,"^((https|http|ftp|rtsp|mms)?:\\/\\/)[^\\s\\/]+(\\/){1}", "");
                                this.weChatMediaRecordData.Update(new WeChatMediaRecordEntity()
                                {
                                    Type = weChatMediaType,
                                    MediaId = mediaId,
                                    FileName = result.item[j].name,
                                    Title = result.item[j].name,
                                    Description = result.item[j].name,
                                    Url = result.item[j].url,
                                    CreatedAt = result.item[j].update_time,
                                    LocalUrl = string.Format("{0}/{1}", configuration["CurrentlyImageHost"], localUrl)
                                });
                            }
                            else
                            {
                                string path = string.Empty;
                                string name = ((long)result.item[j].update_time).ToString();
                                string url = result.item[j].url;
                                string title = result.item[j].name;
                                string description = result.item[j].name;
                                if (weChatMediaType != WeChatMediaType.Image)
                                {
                                    HttpResponseDto httpResponseDto = this.GetWeChatMaterialInfo(mediaId, true);
                                    if (weChatMediaType == WeChatMediaType.Voice)
                                    {
                                        name = name + ".mp3";
                                        path = SaveMediaFile(weChatMediaType, name, httpResponseDto.ResponseData);
                                    }
                                    else
                                    {
                                        dynamic resultValue = JsonConvert.DeserializeObject<dynamic>(httpResponseDto.ResponseMessage);
                                        title = resultValue.title;
                                        description = resultValue.description;
                                        url = resultValue.down_url;
                                        string suffix = ".mp4";
                                        if (string.IsNullOrWhiteSpace(description))
                                        {
                                            description = title;
                                        }
                                        path = SaveImage(weChatMediaType, name + suffix, url);
                                    }
                                }
                                else
                                {
                                    string suffix = url.Substring(url.LastIndexOf("wx_fmt=") + 7);
                                    name = name + "." + suffix;
                                    path = SaveImage(weChatMediaType, name, url);
                                }
                                string localUrl = Regex.Replace(path, "^((https|http|ftp|rtsp|mms)?:\\/\\/)[^\\s\\/]+(\\/){1}", "");
                                this.Add(new WeChatMediaRecordDto()
                                {
                                    Type = weChatMediaType,
                                    MediaId = mediaId,
                                    FileName = result.item[j].name,
                                    Title = title,
                                    Description = description,
                                    Url = url,
                                    CreatedAt = result.item[j].update_time,
                                    LocalUrl = localUrl.Replace("\\", "/")
                                });
                            }
                        }
                    }
                }
            }
        }
        public HttpResponseDto GetWeChatMaterialInfo(string mediaId, bool isPermanent)
        {
            return GetWeChatMaterialInfo(mediaId, isPermanent, false);
        }
        public HttpResponseDto GetWeChatMaterialInfo(string mediaId, bool isPermanent, bool isHD)
        {
            return this.materialService.GetMaterial(mediaId, isPermanent, isHD);
        }
        private string SaveMediaFile(WeChatMediaType weChatMediaType, string name, byte[] fileData)
        {
            string path = string.Format("{0}/{1}", weChatMediaType.ToString().ToLower(), DateTime.Now.ToString("yyyy-MM-dd"));
            string parentDirectory = Directory.GetParent(Directory.GetCurrentDirectory()).FullName;
            string saveDirectory = Path.Combine(parentDirectory, configuration["WebsiteName"]);
            path = Path.Combine(saveDirectory, path);
            if (!File.Exists(path))
            {
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }
                path = Path.Combine(path, name);
                using (FileStream fs = File.Create(path))
                {
                    fs.Write(fileData, 0, fileData.Length);
                }
            }
            return path.Replace(saveDirectory, configuration["CurrentlyImageHost"]);
        }
        private string SaveImage(WeChatMediaType weChatMediaType, string name, string url)
        {
            string path = string.Format("{0}/{1}", weChatMediaType.ToString().ToLower(), DateTime.Now.ToString("yyyy-MM-dd"));
            string parentDirectory = Directory.GetParent(Directory.GetCurrentDirectory()).FullName;
            string saveDirectory = Path.Combine(parentDirectory, configuration["WebsiteName"]);
            path = Path.Combine(saveDirectory, path);
            using (WebClient webClient = new WebClient())
            {
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }
                path = Path.Combine(path, name);
                if (!File.Exists(path))
                {
                    webClient.DownloadFile(url, path);
                }
            }
            return path.Replace(saveDirectory, configuration["CurrentlyImageHost"]);
        }

        public IEnumerable<WeChatMediaRecordDto> UploadTemporaryFileToWeChat()
        {
            return this.weChatMediaRecordData.GetTemporaryFileRecords().As<IEnumerable<WeChatMediaRecordDto>>();
        }
    }
}
